package com.example.app.manager.c1;

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;

import com.example.app.activity.MLog;
import com.example.app.manager.MediaRecorderManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

class Camera1Base {
    private Camera camera;//相机
    private SurfaceHolder surfaceHolder;
    private TextureView previewView;
    private Camera.CameraInfo cameraInfo;
    //false 前置摄像头 true 后置相机
    private boolean isCameraBack = false;
    //相机个数
    private int cameraCount;
    private boolean hasBack, hasFront, hasExternal;
    //真实的预览大小
    private Camera.Size previewSize;
    //拍照大小
    private Camera.Size pictureSize;
    //视频大小
    private Camera.Size vodeiSize;
    //屏幕方向 0,1,2,3
    private int direction;
    private Context context;

    protected void initCameraParameter(int direction, Context context) {
        this.direction = direction;
        this.context = context;
        cameraCount = Camera.getNumberOfCameras();
        for (int i = 0; i < cameraCount; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                // 后置摄像头信息
                hasBack = true;
            }
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                // 前置摄像头信息
                hasFront = true;
            }

        }
    }

    //初始化相机
    protected void initCamera() {
        setZoomRest();
        if (cameraCount == 0) {
            return;
        }
        int id = getCameraId();
        d("开启相机id：" + id);
        if (id < 0) {
            return;
        }
        SurfaceView surface = getSurfaceView();
        if (surface != null) {
            surfaceHolder = getSurfaceView().getHolder();
            //PixelFormat.JPEG
            surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
            surfaceHolder.setKeepScreenOn(true);
            surfaceHolder.addCallback(surfaceCallback);
        }
        if (surface == null) {
            previewView = getPreviewView();
        }
        if (surface == null && previewView == null) {
            d("设置预览错误：previewView 和 SurfaceView 至少设置一个");
            return;
        }
        //
        initData();
        camera = Camera.open(id);
        cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(id, cameraInfo);
        int orientation = cameraInfo.orientation;
        d("initCamera 角度：" + orientation + " isCameraBack:" + isCameraBack);
        //
        Camera.Parameters parameters = camera.getParameters();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        selectPreviewSize(previewSizes);
        List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
        pictureSize = selectPictureSize(pictureSizes);
        List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes();
        vodeiSize = selectPictureSize(videoSizes);
        List<String> focusModesList = parameters.getSupportedFocusModes();
        //增加对聚焦模式的判断
        if (focusModesList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        }
        //parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        parameters.setPreviewSize(previewSize.width, previewSize.height);
        if (pictureSize != null) {
            parameters.setPictureSize(pictureSize.width, pictureSize.height);
        }
        d("previewSize：" + previewSize.width + "  " + previewSize.height);
        d("pictureSize：" + pictureSize.width + "   " + pictureSize.height);
        camera.setParameters(parameters);
        setOrientation();
        //打开摄像头不用 ，切换用到
        try {
            if (surfaceHolder != null) {
                camera.setPreviewDisplay(surfaceHolder);
            } else {
                SurfaceTexture surfaceTexture = previewView.getSurfaceTexture();
                camera.setPreviewTexture(surfaceTexture);
            }
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initData() {
        zoomLevel = 0;
        fingerSpacing = 0;
    }

    private int getCameraId() {
        int cameraID = -1;
        //默认打开前置摄像头
        if (!isCameraBack && hasFront) {
            //前置摄像头
            cameraID = CameraCharacteristics.LENS_FACING_FRONT;
        }
        if (isCameraBack && hasBack) {
            //后置摄像头
            cameraID = CameraCharacteristics.LENS_FACING_BACK;
        }
        return cameraID;
    }

    private void selectPreviewSize(List<Camera.Size> choices) {
        //相机镜头
        Camera.Size cameraLensSize = null;
        //
        int[] sizes = getPreviewWH();
        if (sizes == null || sizes.length < 2) {
            return;
        }
        int previewMin = Math.min(sizes[0], sizes[1]);
        int previewMax = Math.max(sizes[0], sizes[1]);
        int px = previewMin * previewMax;
        double fixationD = (double) previewMin / (double) previewMax;
        double difference = -1;
        d("previewMin：" + previewMin + " previewMax:" + previewMax + " fixation:" + fixationD);
        for (Camera.Size size : choices) {
            int w = size.width;
            int h = size.height;
            double max = Math.max(w, h);
            double min = Math.min(w, h);
            double d = min / max;
            d("预览大小列表 Width：" + w + " Height:" + h + " d:" + d);
            if (cameraLensSize == null) {
                cameraLensSize = size;
                difference = d;
                continue;
            }
            max = Math.max(fixationD, d);
            min = Math.min(fixationD, d);
            double f = min / max;
            if (f == 1 && difference != 1) {
                cameraLensSize = size;
                difference = 1;
                continue;
            }
            int s = cameraLensSize.height * cameraLensSize.width;
            if (f == 1 && difference == 1) {
                if (px == (w * h)) {
                    cameraLensSize = size;
                    difference = 1;
                    break;
                }
                if (s < (w * h)) {
                    cameraLensSize = size;
                    difference = 1;
                }
                continue;
            }
            f = Math.abs(f - d);
            if (difference < 1 && difference > f) {
                cameraLensSize = size;
                difference = f;
                continue;
            }
            if (difference < 1 && difference == f && s < (w * h)) {
                cameraLensSize = size;
                difference = f;
                continue;
            }

        }
        d("选择的预览 Width：" + cameraLensSize.width + " Height:" + cameraLensSize.height);
        previewSize = cameraLensSize;
    }

    //获取合适的照片大小
    private Camera.Size selectPictureSize(List<Camera.Size> choices) {
        int pictureW = previewSize.width;
        int pictureH = previewSize.height;
        Camera.Size photoSize = null;
        int px = pictureW * pictureH;
        double minVideo = Math.min(pictureW, pictureH);
        double maxVideo = Math.max(pictureW, pictureH);
        double fixationD = minVideo / maxVideo;
        double difference = -1;
        for (Camera.Size size : choices) {
            int w = size.width;
            int h = size.height;
            double min = Math.min(w, h);
            double max = Math.max(w, h);
            double d = min / max;
            MLog.e(tag, "照片大小列表 Width：" + w + " Height:" + h + " d:" + d);
            if (photoSize == null) {
                photoSize = size;
                difference = d;
                continue;
            }
            max = Math.max(fixationD, d);
            min = Math.min(fixationD, d);
            double f = min / max;
            if (f == 1 && difference != 1) {
                photoSize = size;
                difference = 1;
                continue;
            }
            int s = photoSize.height * photoSize.width;
            if (f == 1 && difference == 1) {
                if (px == (w * h)) {
                    photoSize = size;
                    difference = 1;
                    break;
                }
                if (s < (pictureW * pictureH)) {
                    photoSize = size;
                    difference = 1;
                }
                continue;
            }
            f = Math.abs(f - d);
            if (difference < 1 && difference > f) {
                photoSize = size;
                difference = f;
                continue;
            }
            if (difference < 1 && difference == f && s < (w * h)) {
                photoSize = size;
                difference = f;
                continue;
            }

        }
        MLog.e(tag, "合适的照片大小 Width：" + photoSize.width
                + " Height:" + photoSize.height);
        return photoSize;
    }

    //设置相机角度
    protected void setOrientation() {
        int orientation = 0;
        d("屏幕方向" + direction);
        switch (String.valueOf(isCameraBack)) {
            case "false":
                //前置摄像头
                //竖屏
                if (direction == Surface.ROTATION_0) {
                    orientation = 90;
                }
                //倒屏
                if (direction == Surface.ROTATION_180) {
                    orientation = 270;
                }
                //右横屏
                if (direction == Surface.ROTATION_90) {
                    orientation = 0;
                }
                //左横屏
                if (direction == Surface.ROTATION_270) {
                    orientation = 180;
                }
                break;
            case "true":
                //一般是后置摄像头
                //竖屏
                if (direction == Surface.ROTATION_0) {
                    orientation = 90;
                }
                //倒屏
                if (direction == Surface.ROTATION_180) {
                    orientation = 270;
                }
                //右横屏
                if (direction == Surface.ROTATION_90) {
                    orientation = 0;
                }
                //左横屏
                if (direction == Surface.ROTATION_270) {
                    orientation = 180;
                }
                break;
        }
        camera.setDisplayOrientation(orientation);
    }

    protected SurfaceView getSurfaceView() {
        return null;
    }

    protected TextureView getPreviewView() {
        return null;
    }

    protected int[] getPreviewWH() {
        return null;
    }


    //获取相机数量
    protected int getCameraCount() {
        return cameraCount;
    }
    //是否开启了相机 true 开启
    protected boolean isOpne() {
        return camera != null;
    }
    protected Camera.Size getPreviewSize() {
        return previewSize;
    }

    public void setCameraBack(boolean isCameraBack) {
        this.isCameraBack = isCameraBack;
    }

    public void setCameraBackSwitchover() {
        boolean isFront = !isCameraBack;
        isCameraBack = isFront;
    }

    //false 前置摄像头 true 后置相机
    public boolean isCameraBack() {
        return isCameraBack;
    }

    protected void startPreview() {
        camera.startPreview();
    }

    protected Camera.CameraInfo getCameraInfo() {
        return cameraInfo;
    }

    // 释放相机资源
    protected void cameraClose() {
        if (camera == null) {
            return;
        }
        camera.release();
        camera = null;
    }

    //===============================
    Boolean isSuppport;

    //聚焦 true 支持聚焦
    protected boolean isSupportZoom() {
        if (isSuppport != null) {
            return isSuppport;
        }
        isSuppport = true;
        if (camera.getParameters().isSmoothZoomSupported()) {
            isSuppport = false;
        }
        return isSuppport;
    }

    //手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2)
    private float fingerSpacing;
    private int zoomLevel = 0;


    //重置缩放
    private void setZoomRest() {
        zoomLevel = 0;
        isSuppport = null;
    }

    //相机缩放
    protected void onCameraZoom(MotionEvent event) {
        if (camera == null) {
            return;
        }
        /*if (!isSupportZoom()) {
            d("不支持缩放");
             return;
        }*/
        Camera.Parameters params = camera.getParameters();
        int maxZoom = params.getMaxZoom();
        if (maxZoom == 0) {
            d("不能缩放 MAX=" + maxZoom);
            return;
        }
        //计算两个触摸点的距离
        float currentFingerSpacing = getFingerSpacing(event);
        if (fingerSpacing != 0) {
            if (currentFingerSpacing > fingerSpacing && maxZoom > zoomLevel) {
                zoomLevel++;

            } else if (currentFingerSpacing < fingerSpacing && zoomLevel > 1) {
                zoomLevel--;
            }
        }
        if (zoomLevel > maxZoom) {
            zoomLevel = maxZoom;
        }
        if (zoomLevel < 0) {
            zoomLevel = 0;
        }
        fingerSpacing = currentFingerSpacing;
        params.setZoom(zoomLevel);
        camera.setParameters(params);
        d("设置缩放成功");
    }

    //计算两个触摸点的距离
    private float getFingerSpacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    private boolean isFocusing;

    protected void onCameraFocus(int x, int y) {
        //正在对焦时   直接返回
        if (camera == null || isFocusing) {
            return;
        }
        isFocusing = true;
        clearCameraFocus();
        //获取聚焦区域
        List<Camera.Area> focuss = new ArrayList();
        Rect focusRect = getLightRect(x, y, 1f);
        focuss.add(new Camera.Area(focusRect, 1000));
        //获取感光区域
        List<Camera.Area> meterings = new ArrayList();
        Rect meteringRect = getLightRect(x, y, 1f);
        meterings.add(new Camera.Area(meteringRect, 1000));
        //
        Camera.Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        //设置聚焦区域
        if (parameters.getMaxNumFocusAreas() > 0) {
            parameters.setFocusAreas(focuss);
        }
        //设置感光区域
        if (parameters.getMaxNumMeteringAreas() > 0) {
            parameters.setMeteringAreas(meterings);
        }
        camera.setParameters(parameters);
        camera.autoFocus(autoFocusCallback);
    }

    //设置感光区域
    private Rect getLightRect(float x, float y, float coefficient) {
        int FOCUS_AREA_SIZE = 300;
        //计算点击坐标点在新的坐标系中的位置
        int[] wh = getPreviewWH();
        int areaSize = Float.valueOf(FOCUS_AREA_SIZE * coefficient).intValue();
        int left = getLightRectclamp(Float.valueOf((y / wh[1]) * 2000 - 1000).intValue(), areaSize);
        int top = getLightRectclamp(Float.valueOf(((wh[0] - x) / wh[0]) * 2000 - 1000).intValue(), areaSize);
        return new Rect(left, top, left + areaSize, top + areaSize);
    }

    // 确保所选区域在合理范围内,不会超过边界值
    private int getLightRectclamp(int touchCoordinateInCameraReper, int focusAreaSize) {
        int result;
        if (Math.abs(touchCoordinateInCameraReper) + focusAreaSize > 1000) {
            if (touchCoordinateInCameraReper > 0) {
                result = 1000 - focusAreaSize;
            } else {
                result = -1000 + focusAreaSize;
            }
        } else {
            result = touchCoordinateInCameraReper - focusAreaSize / 2;
        }
        return result;
    }

    /**
     * 清除自动对焦
     */
    private void clearCameraFocus() {
        if (camera == null) {
            return;
        }
        camera.cancelAutoFocus();
        Camera.Parameters parameters = camera.getParameters();
        parameters.setFocusAreas(null);
        parameters.setMeteringAreas(null);
        camera.setParameters(parameters);
    }

    /**
     * 开关闪光灯
     * <p/>
     * 持续的亮灯FLASH_MODE_TORCH
     * 闪一下FLASH_MODE_ON
     * 关闭模式FLASH_MODE_OFF
     * 自动感应是否要用闪光灯FLASH_MODE_AUTO
     */
    protected void onCameraSwithLight() {
        if (camera == null) {
            return;
        }
        Camera.Parameters parameters = camera.getParameters();
        String t = parameters.getFlashMode();
        d("灯光：" + t);
        if (Camera.Parameters.FLASH_MODE_OFF.equals(t)) {
            //开启闪光灯
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            camera.setParameters(parameters);
            return;
        }
        if (Camera.Parameters.FLASH_MODE_TORCH.equals(t)) {
            //关闭闪光灯
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(parameters);
            return;
        }
        d("不支持闪光灯");

    }

    //重新预览
    protected void setResetPreview() {
        if (camera != null) {
            initData();
            Camera.Parameters params = camera.getParameters();
            params.setZoom(zoomLevel);
            camera.setParameters(params);
            camera.startPreview();
            return;
        }
        initCamera();
    }

    /**
     * 拍照
     *
     * @param shutter
     * @param onPictureCallback
     */
    protected void onCameraTake(Camera.ShutterCallback shutter,
                                Camera.PreviewCallback previewCall, Camera.PictureCallback onPictureCallback) {
        if (camera == null) {
            return;
        }
        if (previewCall != null) {
            camera.setPreviewCallback(previewCall);
        }
        if (onPictureCallback != null) {
            camera.takePicture(shutter, null, onPictureCallback);
        }

    }

    /**
     * 录制视频
     *
     * @param videoPath
     * @param endTime
     */
    public void onCameraVideoStart(String videoPath, int endTime) {
        if (camera == null) {
            return;
        }
        Camera.Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        //设置拍照声音
        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            camera.enableShutterSound(false);
        }*/
        //录像之前要完全停止预览
        camera.stopPreview();
        camera.unlock();
        if (surfaceHolder != null) {
            MediaRecorderManager.getInstance().onInitVideoRecorderWeak(camera, surfaceHolder.getSurface());
        } else {
            SurfaceTexture surfaceTexture = previewView.getSurfaceTexture();
            Surface surface = new Surface(surfaceTexture);
            MediaRecorderManager.getInstance().onInitVideoRecorderWeak(camera, surface);
        }
        //设置录制时间 s
        MediaRecorderManager.getInstance().setRecordTotalTime(endTime);
        //视频大小是需要硬件支持的，如果硬件不支持就会出现错误。start failed: -1
        int videoW = 0;
        int videoH = 0;
        if (vodeiSize != null) {
            videoW = vodeiSize.width;
            videoH = vodeiSize.height;
        }
        d("视频大小 videoW=" + videoW + " videoH=" + videoH);
        MediaRecorderManager.getInstance().setVideoOutput(videoPath, videoW, videoH);
        //MediaRecorderManager.getInstance().setVideoOutput(videoPath,
        //        previewSize.width, previewSize.height);
        //一般前置设置头 90 后置摄像头 270
        int cameraOrientation = cameraInfo.orientation;
        //int cameraOrientation = !isCameraBack ? 90 : 270;
        MediaRecorderManager.getInstance().setPreviewRotate(direction, cameraOrientation);
        MediaRecorderManager.getInstance().setMediaVideoStartWeak();

    }

    //聚焦
    private FocusCallback autoFocusCallback = new FocusCallback();

    class FocusCallback implements Camera.AutoFocusCallback {

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            isFocusing = false;
            d("聚焦结果：" + success);
        }
    }

    //预览
    private SurfaceCallback surfaceCallback = new SurfaceCallback();

    class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            d("surfaceChanged");
            if (camera == null) {
                return;
            }
            d("surfaceChanged---camera");
            camera.startPreview();
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // 将holder，这个holder为开始在onCreate里面取得的holder，将它赋给mSurfaceHolder
            d("surfaceCreated");
            if (camera == null) {
                return;
            }
            d("surfaceCreated--camera");
            try {
                //设置显示
                camera.setPreviewDisplay(holder);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            // surfaceDestroyed的时候同时对象设置为null
            d("surfaceDestroyed");
            if (camera == null) {
                return;
            }
            d("surfaceDestroyed--camera");
            camera.stopPreview();

        }

    }

    private String tag = "Camera1Manager";

    protected void d(String value) {
        MLog.e(tag, value);
    }
}
